package com.bolingcavalry.crm.user.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.ResponseResult;
import com.bolingcavalry.crm.user.domain.Login;
import com.bolingcavalry.crm.user.mapper.PermissionsMapper;
import com.bolingcavalry.crm.user.mapper.RoleMapper;
import com.bolingcavalry.crm.user.mapper.UserMapper;
import com.bolingcavalry.crm.user.service.UserService;
import com.bolingcavalry.crm.user.util.JwtUtil;
import com.dto.*;
import com.dto.user.FlatUserRole;
import com.dto.user.UserDTO;
import com.dto.user.UserRoleListDto;
import com.entity.user.Role;
import com.entity.user.User;
import com.vo.*;
import com.vo.user.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.base.Status.*;
import static org.apache.logging.log4j.util.Strings.isBlank;
import static org.apache.logging.log4j.util.Strings.isNotBlank;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PermissionsMapper permissionsMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private JwtUtil jwtUtil;

    /**
     * 查询角色信息
     * @param username
     * @return
     */
    @Override
    public List<String> getRole(String username) {
        List<String> rolename = userMapper.getRole(username);
        return rolename;
    }

    /**
     * 查询密码
     * @param username
     * @return
     */
    @Override
    public String getPassword(String username) {
        String psw=userMapper.getPassword(username);
        return psw;
    }

    /**
     * 注册校验
     * @param user
     * @return
     */
    @Override
    @Transactional
    public Boolean insect(UserDTO user) {
        //判断用户名是否存在
        User existUser = userMapper.selectByName(user.getUsername());
        if(existUser!=null){
            //说明用户名已经存在
            return false;
        }
        //创建User实体类
        User u = new User();
        u.setUsername(user.getUsername());
        u.setPassword(user.getPassword());
        u.setEmail(user.getEmail());
        u.setMobile(user.getMobile());
        u.setNickname(user.getNickname());
        u.setAvatar(user.getAvatar());
        u.setCreateTime(LocalDateTime.now());
        try {
            userMapper.insert(u);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        //将userdto的角色信息传入user_role中间表中
        //查询角色id
        if(user.getRoles()!=null)
        for (String role : user.getRoles()) {
            LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Role::getName, role);
            Role role1 = roleMapper.selectOne(queryWrapper);
            //插入中间表user_role
            userMapper.insertUserRole(u.getId(), role1.getId());
        }

        return true;
    }

    /**
     * 根据角色名获取角色id
     * @param role
     * @return
     */
    @Override
    public Long getRoleIdByRoleName(String role) {
        return userMapper.getRoleIdByRoleName(role);
    }

    /**
     * 根据角色id获取权限名称和id
     * @param roleId
     * @return
     */
    @Override
    public List<PermissionVO> getPermissionsByRoleId(Long roleId) {
        return userMapper.getPermissionsByRoleId(roleId);
    }

    /**
     * 添加权限
     * @param permissionDTO
     */
    @Override
    public void addPermission(PermissionDTO permissionDTO) {
        String roleName = permissionDTO.getRoleName();
        for (String permissionName : permissionDTO.getPermissionsName()) {
            permissionsMapper.insertPR(permissionName, roleName);
        }
    }

    /**
     * 查询角色名称和id
     * @return
     */
    @Override
    public List<RoleVO> getRoleAndId() {
        return userMapper.getRoleAndId();
    }

    /**
     * 添加角色
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional
    public Boolean addRole(RoleDTO roleDTO) {
        Role role = new Role();
        BeanUtils.copyProperties(roleDTO, role);
        try {
            roleMapper.insert(role);
            //提取权限名称查询权限id，跟角色id一起插入中间表
            for (String permissionName : roleDTO.getPermissions()) {
                permissionsMapper.insertPR(permissionName, role.getName());
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 查询用户当前状态
     * @return
     */
    @Override
    public List<UserStatusVO> getUserStatus() {
        return userMapper.getUserStatus();
    }

    /**
     * 分页条件查询
     * @param pageNum
     * @param pageSize
     * @param status
     * @param username
     * @param nickname
     * @return
     */
    @Override
    public IPage<UserDTO> getByConditions(Integer pageNum, Integer pageSize, String status, String username, String nickname) {
        // 处理分页参数
        Page<UserVO> page;
        if (pageSize == null) {
            // 查询全部数据，使用足够大的页面大小
            page = new Page<>(1, 100000);
        } else {
            // 正常分页
            page = new Page<>(pageNum, pageSize);
        }

        IPage<UserVO> resultPage = userMapper.getByConditions(page, status, username, nickname);

        //查询出来的数据不包含roles和permissions，需要重新查询
        List<UserVO> userVOList = resultPage.getRecords();
        if (userVOList != null && !userVOList.isEmpty()) {
            for (UserVO userVO : userVOList) {
                userVO.setRoles(userMapper.getRoleNameByUserId(userVO.getId()));
                List<Long> roleIdsByUserId = userMapper.getRoleIdsByUserId(userVO.getId());
                if(roleIdsByUserId != null && !roleIdsByUserId.isEmpty())
                    userVO.setPermissions(permissionsMapper.getPermissionsByRoleIds(roleIdsByUserId));
            }
        }
        //转为DTO
        List<UserDTO> userDTOList = new ArrayList<>();
        for (UserVO vo : userVOList) {
            UserDTO dto = new UserDTO();
            BeanUtils.copyProperties(vo, dto);
            userDTOList.add(dto);
        }

        // 3. 构造分页的 DTO 返回结果
        Page<UserDTO> dtoPage = new Page<>();
        dtoPage.setCurrent(resultPage.getCurrent());
        dtoPage.setSize(resultPage.getSize());
        dtoPage.setTotal(resultPage.getTotal());
        dtoPage.setPages(resultPage.getPages());
        dtoPage.setRecords(userDTOList);

        // 如果是查询全部，调整分页信息
        if (pageSize == null) {
            dtoPage.setPages(1);
            dtoPage.setCurrent(1);
            dtoPage.setSize(dtoPage.getTotal());
        }

        return dtoPage;
    }


    /**
     * 修改用户信息
     * @param userDTO
     * @return
     */
    @Override
    @Transactional
    public Boolean update(UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);

        // 如果传了新密码则加密
        if (userDTO.getPassword() != null && !userDTO.getPassword().isEmpty()) {
            user.setPassword(BCrypt.hashpw(userDTO.getPassword(), BCrypt.gensalt()));
        }

        // 只有当roles不为null时才更新角色信息
        if (userDTO.getRoles() != null) {
            // 先删除原有角色
            userMapper.deleteurbyuserId(user.getId());

            // 重新分配角色
            for (String roleName : userDTO.getRoles()) {
                LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Role::getName, roleName);
                Role role = roleMapper.selectOne(queryWrapper);
                if (role != null) {
                    userMapper.insertUserRole(user.getId(), role.getId());
                }
            }
        }
        // 更新用户基本信息
        return this.userMapper.updateById(user) > 0;
    }


    /**
     * 删除用户信息
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Boolean deleteById(Long id) {
        //先删除中间表数据
        userMapper.deleteurbyuserId(id);
        return userMapper.deleteById(id) > 0;
    }

    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    @Override
    public UserDTO getUserById(Long id) {
        UserDTO userDTO = new UserDTO();
        User user =userMapper.selectById(id);
        //根据userId查询角色name
        List<String> roles = userMapper.getRoleNameByUserId(id);
        //根据userId查询角色id
        List<Long> roleIds = userMapper.getRoleIdsByUserId(id);
        //根据角色id查询权限列表
        List<String> permissions = permissionsMapper.getPermissionsByRoleIds(roleIds);
        BeanUtils.copyProperties(user, userDTO);
        userDTO.setPermissions(permissions);
        userDTO.setRoles(roles);
        return userDTO;
    }


    /**
     * 获取用户当前状态数量
     * @return
     */
    @Override
    public UserStatusCountVO getUserStatusCount() {
        UserStatusCountVO vo = new UserStatusCountVO();
        //服务外出
        vo.setOnDutyCount(userMapper.countByStatus(USER_STATUS_ON_AFTER_SALES_TRIP));
        //在岗办公
        vo.setBusinessTripCount(userMapper.countByStatus(USER_STATUS_ON_DUTY));
        //公务外出
        vo.setOfficialBusinessCount(userMapper.countByStatus(USER_STATUS_ON_BUSINESS_TRIP));
        return vo;
    }

    @Override
    public Boolean userupdate(UserDTO userDTO) {
        //修改状态、修改个人信息、修改密码
        User user = new User();
        BeanUtils.copyProperties(userDTO,user);
        return userMapper.updateById(user) > 0;
    }

    //获取用户
    @Override
    public User checkOpenid(String openid) {
        //数据库中检查是否有该用户的openid，如果有则对应的user
        return userMapper.checkOpenid(openid);
    }


    //登录
    @Override
    public ResponseResult<Map<String, Object>> login(Login login) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, login.getUsername());
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            return ResponseResult.error("用户不存在");
        }
        //校验用户名密码
        if (authenticate(login.getUsername(), login.getPassword())){
            //获取角色
            List<String> role = getRole(login.getUsername());
            List<String> permissionsName = new ArrayList<>();
            //获取角色id
            for (String s : role) {
               Long roleId = getRoleIdByRoleName(s);
                List<PermissionVO> permissions = getPermissionsByRoleId(roleId);
                for (PermissionVO permissionVO : permissions) {
                    permissionsName.add(permissionVO.getPermissionName());
                }
            }
            // 手动创建认证对象
            List<GrantedAuthority> authorities = new ArrayList<>();
            for (String roleName : role) {
                authorities.add(new SimpleGrantedAuthority(roleName));
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    login.getUsername(),
                    null,
                    authorities
            );
            // 将认证信息存入 SecurityContext
            SecurityContextHolder.getContext().setAuthentication(authentication);
            //生成token令牌，传入用户名和角色信息，通过tokenutils生成包含role的token，后续方便secuity的角色验证
            String token = jwtUtil.createToken(login.getUsername(), role, permissionsName);
            // 封装数据到 Map
            Map<String, Object> data = new HashMap<>();
            data.put("token", token);
            data.put("role", role);
            data.put("permissions", permissionsName);
            return ResponseResult.success(data);
        } else {
            return ResponseResult.error("用户名或密码错误");
        }
    }

    @Override
    public ResponseResult<Map<String, Object>> wxtoken(String username) {
        // 获取角色列表
        List<String> role = getRole(username);

        // 获取权限列表
        List<String> permissionsName = new ArrayList<>();
        for (String roleName : role) {
            Long roleId = getRoleIdByRoleName(roleName);
            List<PermissionVO> permissions = getPermissionsByRoleId(roleId);
            for (PermissionVO permissionVO : permissions) {
                permissionsName.add(permissionVO.getPermissionName());
            }
        }

        // 创建认证对象（支持多个角色）
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (String roleName : role) {
            authorities.add(new SimpleGrantedAuthority(roleName));
        }

        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                username,
                null,
                authorities
        );
        // 将认证信息存入 SecurityContext
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //生成token令牌，传入用户名和角色信息，通过tokenutils生成包含role的token，后续方便secuity的角色验证
        String token = jwtUtil.createToken(username, role, permissionsName);
        // 封装数据到 Map
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("role", role);
        data.put("permissions", permissionsName);
        return ResponseResult.success(data);
    }

    /**
     * openid绑定
     * @param userDTO
     * @return
     */
    @Override
    public ResponseResult<String> openidbind(UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO,user);
        //校验密码
        if(!authenticate(user.getUsername(), user.getPassword())){
            return ResponseResult.error("密码错误");
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,user.getUsername());
        User user1 = userMapper.selectOne(queryWrapper);
        if(user1 != null && isBlank(user1.getOpenid())){
            user1.setOpenid(user.getOpenid());
            userMapper.updateById(user1);
            return ResponseResult.success("绑定成功");
        } else if (user1 != null && isNotBlank(user1.getOpenid())) {
            return ResponseResult.error("该用户已绑定微信");
        }
        return ResponseResult.error("该账号不存在");
    }

    @Override
    public UserVO getUserVO(String username) {
        //获取用户信息
        UserVO userVO =userMapper.getUserVO(username);
        //查询对应的角色列表和权限列表
        Long id = userVO.getId();
        //根据用户id查询对应的角色id列表
        List<Long> roleIds = userMapper.getRoleIdsByUserId(id);
        List<String> permissions = new ArrayList<>();
        //角色列表
        List<String> roleNames = userMapper.getRoleNameByUserId(id);
        userVO.setRoles(roleNames);
        for (Long roleId : roleIds) {
            //根据id查询权限列表name？
            List<String> permission =permissionsMapper.getpermissionsByRoleId(roleId);
            permissions.addAll(permission);
        }
        userVO.setPermissions(permissions);
        return userVO;
    }

    @Override
    public ResponseResult<String> updatePassword(PasswordDTO passwordDTO) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,passwordDTO.getUsername());
        User user = userMapper.selectOne(queryWrapper);
        if(user!=null){
            String oldPassword = passwordDTO.getOldPassword();
            String newPassword = passwordDTO.getNewPassword();
            //旧密码校验
            if(!authenticate(user.getUsername(), oldPassword)){
                return ResponseResult.error("旧密码输入错误请核对");
            }
            //修改密码
            String hashpw = BCrypt.hashpw(passwordDTO.getNewPassword(), BCrypt.gensalt());
            passwordDTO.setNewPassword(hashpw);
            userMapper.updatePassword(passwordDTO);
            return ResponseResult.success("修改成功");
        }
        return ResponseResult.error("用户不存在");
    }

    @Override
    public User findByOpenId(String openid) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,openid);
        return userMapper.selectOne(queryWrapper);
    }

    // UserServiceImpl 实现
    @Override
    public List<UserRoleListVo> getUserList(UserRoleListDto requestDto) {
        List<UserRoleListVo> userVOList = new ArrayList<>();

        // 获取角色名列表
        List<String> roleNames = new ArrayList<>();
        if (requestDto != null && requestDto.getRoleNames() != null && !requestDto.getRoleNames().isEmpty()) {
            roleNames = requestDto.getRoleNames();
        }

        // 如果传入的角色名列表为空或null，则查询所有角色
        if (roleNames.isEmpty()||requestDto==null) {
            // 查询全部的角色的介绍
            List<RoleVO> allRoleNames = userMapper.getRoleAndId();
            for (RoleVO roleVO : allRoleNames) {
                roleNames.add(roleVO.getDescription());
            }
        }

        // 遍历每个角色名，查询对应的用户列表
        for (String roleName : roleNames) {
            // 根据角色名查询对应的用户列表（扁平结构）
            List<FlatUserRole> flatUserRoles = userMapper.getUserList(roleName);
            // 转换为UserRoleListVo格式
            if (flatUserRoles != null && !flatUserRoles.isEmpty()) {
                // 创建结果对象
                UserRoleListVo result = new UserRoleListVo();
                result.setRoleName(flatUserRoles.get(0).getRoleName()); // 角色名都是一样的
                // 收集所有昵称
                List<String> nickNames = new ArrayList<>();
                for (FlatUserRole flatUserRole : flatUserRoles) {
                    nickNames.add(flatUserRole.getNickname());
                }
                result.setNickName(nickNames);
                userVOList.add(result);
            } else {
                // 如果该角色没有用户，也添加一个空的条目
                UserRoleListVo result = new UserRoleListVo();
                result.setRoleName(roleName);
                result.setNickName(new ArrayList<>());
                userVOList.add(result);
            }
        }

        return userVOList;
    }

    @Override
    public List<String> getAllUserList(String nickName) {
        if(nickName == null || nickName.isEmpty()){
            return userMapper.getNicknameAll();
        }
        // 根据昵称模糊查询用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(User::getNickname, nickName);
        List<User> users = userMapper.selectList(queryWrapper);

        // 提取用户名列表
        return users.stream()
                .map(User::getNickname)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserlocationVO> getUserListByStatus(String status) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getStatus,status);
        List<User> users = userMapper.selectList(queryWrapper);
        // 将User实体映射到UserlocationVO
        return users.stream()
                .map(user -> {
                    UserlocationVO vo = new UserlocationVO();
                    vo.setId(user.getId());
                    vo.setUsername(user.getUsername());
                    vo.setNickname(user.getNickname());
                    vo.setStatus(user.getStatus());
                    vo.setLocation(user.getLocation());
                    return vo;
                })
                .collect(Collectors.toList());
    }



    //密码校验
    private boolean authenticate(String username, String password) {
        String hashpw= getPassword(username);
        //密码解密，校验
        if (BCrypt.checkpw(password, hashpw)) {
            return true;
        } else {
            return false;
        }
    }





}

